Microsoft DirectX 8.1 (C++)

Video Capture Example Code

The following example shows the basic steps needed for a capture application. This is not a robust application. The limitations of this example include:

Note   This example uses the ATL CComPtr class, which automatically manages reference counts. If you prefer to use raw interface pointers, remember to release every interface when you are done with it.

See Also

#include <dshow.h>
#include <atlbase.h>
#include <stdio.h>

HRESULT FindMyCaptureDevice(IBaseFilter **pF, BSTR bstrName)
{
    HRESULT hr = E_FAIL;
    CComPtr<IBaseFilter> pFilter;
    CComPtr<ICreateDevEnum> pSysDevEnum;
    CComPtr<IEnumMoniker> pEnumCat = NULL;
    
    // Create the System Device Enumerator.
    pSysDevEnum.CoCreateInstance(CLSID_SystemDeviceEnum);
    // Obtain a class enumerator for the video compressor category.
    pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0);
    
    // Enumerate the monikers.
    CComPtr<IMoniker> pMoniker;
    ULONG cFetched;
    while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
    {
        CComPtr<IPropertyBag> pProp;
        pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pProp);
        VARIANT varName;
        VariantInit(&varName); // Try to match the friendly name.
        hr = pProp->Read(L"FriendlyName", &varName, 0); 
        if (SUCCEEDED(hr) && (wcscmp(bstrName, varName.bstrVal) == 0))
        {
            hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pFilter);
            break;
        }
        VariantClear(&varName);
        pMoniker = NULL; // Release for the next loop.
    }
    *pF = pFilter;
    (*pF)->AddRef();  // Add ref on the way out.
    return hr;
}

void DoCapture()
{
    HRESULT hr;
    CComBSTR bstrName("My Camera Device");
    CComPtr<IBaseFilter> pSrc;
    CComPtr<IGraphBuilder> pGraph;
    CComPtr<ICaptureGraphBuilder2> pBuilder;
    
    // Create the filter graph.
    hr = pGraph.CoCreateInstance(CLSID_FilterGraph);
    
    // Create the capture graph builder.
    hr = pBuilder.CoCreateInstance(CLSID_CaptureGraphBuilder2);
    pBuilder->SetFiltergraph(pGraph);    
    
    hr = FindMyCaptureDevice(&pSrc, bstrName);
    hr = pGraph->AddFilter(pSrc, L"Capture");
    
    // Create the file-writing portion.
    CComPtr<IBaseFilter> ppf;
    hr = pBuilder->SetOutputFileName(&MEDIASUBTYPE_Avi, 
             L"C:\\Example.avi", &ppf, NULL);

    // Render streams.
    hr = pBuilder->RenderStream(
        &PIN_CATEGORY_CAPTURE,  // Pin category
        &MEDIATYPE_Video,       // Media type
        pSrc,                   // Capture filter
        NULL,                   // Compression filter (optional)
        ppf                     // Multiplexer or renderer filter
    );
    hr = pBuilder->RenderStream(
        &PIN_CATEGORY_PREVIEW,  // Pin category
        &MEDIATYPE_Video,       // Media type
        pSrc,                   // Capture filter
        NULL,                   // Compression filter (optional)
        NULL                     // Default renderer
    );

    // Run the graph.
    const long ONE_SECOND = 10000000; 
    REFERENCE_TIME rtStart = 5 * ONE_SECOND , rtStop = 10 * ONE_SECOND;
    hr = pBuilder->ControlStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, 
        pSrc, &rtStart, &rtStop, 0, 0);
    if (FAILED(hr)) 
    {
        printf("Failed ControlStream.\n");
        return;
    }
    CComQIPtr<IMediaControl> pControl(pGraph);
    CComQIPtr<IMediaEventEx> pEvent(pGraph);
    hr = pControl->Run();
    while (1)
    {
        long evCode, lParam1, lParam2;
        hr = pEvent->GetEvent(&evCode, &lParam1, &lParam2, 100);
        if (hr == S_OK)
        {
            hr = pEvent->FreeEventParams(evCode, lParam1, lParam2);
            if (evCode == EC_STREAM_CONTROL_STARTED)
            {
                printf("Starting capture...\n");
            }
            else if (evCode == EC_STREAM_CONTROL_STOPPED)
            {
                break;
            }
        }
    }
    pControl->Stop();
    printf("... Done\n");
}

int __cdecl main()
{
    CoInitialize(NULL);
    DoCapture();        
    CoUninitialize();
    return 0;
}